﻿using System.Data.Entity;
using Nop.Core.Data;
using Nop.Core.Domain.Messages;
using Nop.Plugin.Misc.TabManager.Domain;
using Nop.Services.Catalog;
using Nop.Services.Configuration;
using Nop.Services.Messages;
using Nop.Web.Framework.Controllers;
using Nop.Web.Framework.Kendoui;
using Nop.Web.Framework.Mvc;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Web.Mvc;
using Nop.Core.Infrastructure;
using Nop.Core;
using Nop.Plugin.Misc.TabManager.Models;
using Nop.Services.Topics;
using Nop.Data;
using Nop.Core.Caching;
using Nop.Core.Domain;
using Nop.Plugin.Misc.TabManager.Services;

namespace Nop.Plugin.Misc.TabManager.Controllers
{
    public class TabManagerController : BasePluginController
    {
        private ITabManagerService _tabSvc;
        private ISettingService _settings;
        private IDbContext _dbContext;
        private ITopicService _topics;
        private readonly ICacheManager _cacheMgr;
        private int UserId { get; set; }

        public TabManagerController(ITabManagerService tabService
                                  , ISettingService settingService
                                  , ITopicService topicService
                                  , ICacheManager cacheMgr
                                  , IDbContext dbCtx)
        {
            _tabSvc = tabService;
            _cacheMgr = cacheMgr;
            _settings = settingService;
            _topics = topicService;
            _dbContext = dbCtx;


            if (EngineContext.Current.Resolve<IWorkContext>().CurrentCustomer != null)
            {
                UserId = EngineContext.Current.Resolve<IWorkContext>().CurrentCustomer.Id;
            }
        }
        [AdminAuthorize]
        public ActionResult ManageTabs()
        {
            if (Request.Form.AllKeys.Count() > 0)
            {
                TabUpdate();
            }

            var Tabs = (from tab in _tabSvc.GetAll()
                        where tab.ParentTabId == null
                        orderby tab.TabOrder
                        select (new TabTv { Id = tab.Id, ParentTabId = tab.ParentTabId, TabName = tab.TabName, HasChildren = false })).ToList();
            StringBuilder sbTabs = new StringBuilder("<ul id=\"menusmpl\">");

            foreach (TabTv tv in Tabs)
            {
                var ChildTabs = (from tab in _tabSvc.GetAll()
                                 where tab.ParentTabId == tv.Id
                                 orderby tab.TabOrder
                                 select (new TabTv { Id = tab.Id, ParentTabId = tab.ParentTabId, TabName = tab.TabName })).ToList();
                if (ChildTabs != null && ChildTabs.Count() > 0)
                {
                    sbTabs.AppendFormat("<li>{0}<ul>", tv.TabName);

                    foreach (TabTv tvChild in ChildTabs)
                    {
                        sbTabs.AppendFormat("<li>{0}</li>", tvChild.TabName);
                    }

                    sbTabs.Append("</ul></li>");
                }
                else
                {
                    sbTabs.AppendFormat("<li>{0}</li>", tv.TabName);
                }

            }
            sbTabs.Append("</ul>");

            ViewBag.SampleMenuITems = sbTabs.ToString();

            sbTabs = null;

            SuccessNotification("Your menu item has been saved.");

            return View("~/Plugins/Misc.TabManager/Views/ManageTabs.cshtml");
        }

        /// <summary>
        /// configure tab settings
        /// </summary>
        /// <returns></returns>
        [AdminAuthorize]
        public ActionResult ConfigureTabs()
        {
            //settings
            var tabSettings = _settings.LoadSetting<TabSettings>();

            if (tabSettings == null)
                tabSettings = new TabSettings();

            if (Request.Form.AllKeys.Length > 0)
            {

                if (Request.Form["CacheMenuItems"] != null)
                {
                    tabSettings.CacheMenuItems = Request.GetBoolean("CacheMenuItems");
                }

                if (Request.Form["IncludeTopics"] != null)
                {
                    tabSettings.IncludeTopics = Request.GetBoolean("IncludeTopics");
                }

                if (Request.Form["IncludeCategories"] != null)
                {
                    tabSettings.IncludeCategories = Request.GetBoolean("IncludeCategories");
                }

                if (Request.Form["TrackChangeHistory"] != null)
                {
                    tabSettings.TrackChangeHistory = Request.GetBoolean("TrackChangeHistory");
                }

                if (Request.Form["UseKendoUIMenu"] != null)
                {
                    tabSettings.UseKendoUIMenu = Request.GetBoolean("UseKendoUIMenu");
                }

                if (Request.Form["MainMenuClass"] != null)
                {
                    tabSettings.MainMenuClass = Request.GetString("MainMenuClass");
                }

                if (Request.Form["SubMenuContainerClass"] != null)
                {
                    tabSettings.SubMenuContainerClass = Request.GetString("SubMenuContainerClass");
                }

                if (Request.Form["SubMenuClass"] != null)
                {
                    tabSettings.SubMenuClass = Request.GetString("SubMenuClass");
                }

                if (Request.Form["MenuItemClass"] != null)
                {
                    tabSettings.MenuItemClass = Request.GetString("MenuItemClass");
                }

                _settings.SaveSetting(tabSettings);

                if (tabSettings.IncludeTopics || Request.Form["hdnTopcis"] != null)
                {
                    var rtn = _dbContext.ExecuteSqlCommand("exec Tabs_GetTopics", false, 30);
                    ViewBag.TopicsMessage = string.Concat(rtn, " Topics have been mapped to tabs");

                    //call existing tabs
                    CacheAllTabs();
                }
            }

            TabSettingsViewModel settings = new TabSettingsViewModel
            {
                CacheMenuItems = tabSettings.CacheMenuItems,
                IncludeTopics = tabSettings.IncludeTopics,
                IncludeCategories = tabSettings.IncludeCategories,
                TrackChangeHistory = tabSettings.TrackChangeHistory,
                UseKendoUIMenu = tabSettings.UseKendoUIMenu,
                MainMenuClass = tabSettings.MainMenuClass,
                SubMenuContainerClass = tabSettings.SubMenuContainerClass,
                SubMenuClass = tabSettings.SubMenuClass,
                MenuItemClass = tabSettings.MenuItemClass
            };

            return View("~/Plugins/Misc.TabManager/Views/Configure.cshtml", settings);
        }


        /// <summary>
        /// retrieves tabs for display in menu
        /// </summary>
        /// <returns></returns>
        public ActionResult TabMenu()
        {
            var tabSettings = _settings.LoadSetting<TabSettings>();

            var mainMenuClass = tabSettings.MainMenuClass;
            var subMenuContainerClass = tabSettings.SubMenuContainerClass;
            var subMenuClass = tabSettings.SubMenuClass;
            var menuItemClass = tabSettings.MenuItemClass;

            ViewBag.MainMenuClass = mainMenuClass;
            ViewBag.SubMenuContainerClass = subMenuContainerClass;

            var useKendoUIMenu = tabSettings.UseKendoUIMenu;
            //useKendoUIMenu = useKendoUIMenu == null ? false : useKendoUIMenu;

            string urlFrmt = "<li><a href=\"{0}\">{1}</a>" + (!useKendoUIMenu ? "<div class=\"" + subMenuContainerClass + "\"></div>" : "") + "</li>";
            var supportResponsive = EngineContext.Current.Resolve<StoreInformationSettings>().ResponsiveDesignSupported;

            StringBuilder sbTabs = new StringBuilder();
            foreach (Tab tv in (from tab in GetAllTabs()
                                where (tab.ParentTabId == null && tab.IsVisible == true && tab.IsActive == true && tab.IsDeleted == false)
                                                               && (tab.LogOnRequired == false || (Request.IsAuthenticated && tab.LogOnRequired == true))
                                select tab))
            {
                GetChildMenuItem(useKendoUIMenu, urlFrmt, sbTabs, tv);
            }

            ViewBag.UseKendoUIMenu = useKendoUIMenu; // == null ? false : useKendoUIMenu;
            ViewBag.MenuItems = sbTabs.ToString();
            ViewBag.SupportResponsive = supportResponsive;

            sbTabs = null;
            tabSettings = null;

            return View("~/Plugins/Misc.TabManager/Views/TabMenu.cshtml");
        }



        [HttpPost]
        public JsonResult GetTab(int id)
        {
            var tab = _tabSvc.GetById(id);

            return Json(tab);
        }

        /// <summary>
        /// retrieves all tabs
        /// </summary>
        /// <param name="command"></param>
        /// <returns></returns>
        [HttpPost]
        public JsonResult GetTabs(DataSourceRequest command)
        {
            var Tabs = (from tab in GetAllTabs()
                        select (new TabTv { Id = tab.Id, ParentTabId = tab.ParentTabId, TabName = tab.TabName })).ToList();

            var gridModel = new DataSourceResult
            {
                Data = Tabs,
                Total = Tabs.Count
            };

            return Json(gridModel);
        }

        /// <summary>
        /// retrieves tabs for treeview display
        /// </summary>
        /// <returns></returns>
        [HttpPost]
        public JsonResult GetTabsTv()
        {
            var Tabs = (from tab in GetAllTabs()
                        where tab.ParentTabId == null
                        orderby tab.TabOrder
                        select (new TabTv { Id = tab.Id, ParentTabId = tab.ParentTabId, TabName = tab.TabName, HasChildren = false })).ToList();

            foreach (TabTv tv in Tabs)
            {
                tv.ChildTabs = (from tab in _tabSvc.GetAll()
                                where tab.ParentTabId == tv.Id
                                orderby tab.TabOrder
                                select (new TabTv { Id = tab.Id, ParentTabId = tab.ParentTabId, TabName = tab.TabName })).ToList();
                tv.HasChildren = (tv.ChildTabs != null && tv.ChildTabs.Count > 0);
            }

            return Json(Tabs);
            //return Json(new { Data = Tabs }, JsonRequestBehavior.AllowGet); 
        }

        /// <summary>
        /// updtes treeview changes to tabs...order and parent child relationship
        /// </summary>
        /// <param name="tabs"></param>
        /// <returns></returns>
        [HttpPost]
        public JsonResult UpdateTabs(TabTv[] tabs)
        {
            if (tabs != null && tabs.Length > 0)
            {
                for (int ictr = 0; ictr < tabs.Length; ictr++)
                {
                    if (tabs[ictr].Id > 0)
                    {
                        var tab = _tabSvc.GetById(tabs[ictr].Id);
                        if (tab != null)
                        {
                            if (!tab.ParentTabId.HasValue)
                                tab.TabOrder = ictr + 1;

                            tab.LastModifiedDate = DateTime.UtcNow;
                            tab.LastModifiedUserId = UserId;
                            tab.ParentTabId = tabs[ictr].ParentTabId;
                            tab.TabLevel = tabs[ictr].ParentTabId == null ? 1 : 2;
                            tab.HasChildren = (tabs.Where(s => s.ParentTabId == s.Id).Count() > 0);

                            _tabSvc.UpdateTab(tab);
                        }
                        tab = null;
                    }
                }
            }
            //call existing tabs
            CacheAllTabs();

            SuccessNotification("Tab changes saved");
            return Json("complete", JsonRequestBehavior.DenyGet);
        }

        #region helpers

        [NonAction]
        private void GetChildMenuItem(bool useKendoUIMenu, string urlFrmt, StringBuilder sbTabs, Tab tv)
        {
            var tabSettings = _settings.LoadSetting<TabSettings>();

            var mainMenuClass = tabSettings.MainMenuClass;
            var subMenuContainerClass = tabSettings.SubMenuContainerClass;
            var subMenuClass = tabSettings.SubMenuClass;
            var menuItemClass = tabSettings.MenuItemClass;

            var ChildTabs = (from tab in GetAllTabs()
                             where tab.ParentTabId == tv.Id
                             where (tab.IsVisible == true && tab.IsActive == true && tab.IsDeleted == false)

                             orderby tab.TabOrder
                             select tab).ToList();

            if (ChildTabs != null && ChildTabs.Count() > 0)
            {
                sbTabs.AppendFormat("<li class=\"{0}\"><a href=\"{1}\">{2}</a>", menuItemClass, GetURLForTab(tv), tv.Title);
                if (!useKendoUIMenu)
                {
                    sbTabs.AppendFormat("<div class=\"" + subMenuContainerClass + "\"></div><ul class=\"" + subMenuClass + "\">");
                }
                else
                    sbTabs.Append("<ul>");

                foreach (Tab tvChild in ChildTabs)
                {
                    if (!tv.LogOnRequired)
                    {
                        sbTabs.AppendFormat(urlFrmt, GetURLForTab(tvChild), tvChild.Title);
                    }
                    else if (tv.LogOnRequired && Request.IsAuthenticated)
                    {
                        sbTabs.AppendFormat(urlFrmt, GetURLForTab(tvChild), tvChild.Title);
                    }

                    //   GetChildMenuItem(useKendoUIMenu, urlFrmt, sbTabs, tvChild);
                }
                sbTabs.Append("</ul></li>");
            }
            else
            {
                sbTabs.AppendFormat(urlFrmt, GetURLForTab(tv), tv.Title);
            }

            tabSettings = null;
        }

        /// <summary>
        /// handles changes from the tab form in the UI
        /// </summary>
        /// <param name="formCollection"></param>
        /// <returns></returns>
        [NonAction]
        public void TabUpdate()
        {
            Tab tab = new Tab();

            int id = 0;
            if (int.TryParse(Request.Form["hid"], out id) && id > 0)
            {
                tab = _tabSvc.GetById(id);
                tab.TabOrder = Request.GetInteger("TabOrder");
            }
            else
            {
                tab.TabOrder = 15;//go to bottom
                tab.TabLevel = 1;
                tab.HasChildren = false;
            }

            tab.TabName = Request.Form["TabName"];
            tab.Title = Request.Form["Title"];
            tab.LogOnRequired = Request.GetBoolean("LogOnRequired");
            tab.CultureCode = ""; // Request.Form["CultureCode"];
            tab.Description = Request.Form["Description"];

            //Future implementation
            //tab.StoreId = null; //DateTime.Parse(Request.Form["StoreId"];

            tab.StartDate = Request.GetDate("StartDate");
            tab.EndDate = Request.GetDate("EndDate");

            tab.DisableLink = Request.GetBoolean("DisableLink");
            tab.IsActive = Request.GetBoolean("IsActive");
            tab.IsDeleted = Request.GetBoolean("IsDeleted");
            tab.IsSecure = Request.GetBoolean("IsSecure");
            tab.IsVisible = Request.GetBoolean("IsVisible");

            tab.KeyWords = Request.Form["KeyWords"];
            if (Request.GetInteger("ParentTabId") > 0)
                tab.ParentTabId = Request.GetInteger("ParentTabId");
            else
                tab.ParentTabId = null;

            tab.PermanentRedirect = Request.GetBoolean("IsVisible");
            tab.PermanentRedirectUrl = Request.Form["PermanentRedirectUrl"];

            tab.TabController = Request.Form["TabController"];
            tab.TabControllerAction = Request.Form["TabControllerAction"];

            if (id > 0)
            {
                tab.LastModifiedDate = DateTime.UtcNow;
                tab.LastModifiedUserId = UserId;
                _tabSvc.UpdateTab(tab);
            }
            else
            {
                tab.CreatedDate = DateTime.UtcNow;
                tab.CreatedUserId = UserId;
                _tabSvc.InsertTab(tab);
            }

            //call existing tabs
            CacheAllTabs();
        }

        [NonAction]
        private string GetURLForTab(Tab tv)
        {

            string urlScheme = tv.IsSecure ? "https://" : "http://" + Request.Url.Host;

            if (tv.TopicId.HasValue && tv.TopicId > 0)
            {
                return urlScheme + "/" + tv.PermanentRedirectUrl;
            }
            else if (tv.PermanentRedirect && !string.IsNullOrWhiteSpace(tv.PermanentRedirectUrl))
            {
                return tv.PermanentRedirectUrl.ToLower().StartsWith("http") ? tv.PermanentRedirectUrl : urlScheme + "/" + tv.PermanentRedirectUrl;
            }
            else if (!string.IsNullOrWhiteSpace(tv.TabController) && !string.IsNullOrWhiteSpace(tv.TabControllerAction))
            {
                //TODO: trying to figure out why url contains http://domain/controller?action=actionName
                return urlScheme + Url.Action(tv.TabControllerAction, tv.TabController).Replace("?action=", "/");
            }
            else
            {
                return urlScheme + Url.RouteUrl(tv.TabName);
            }
        }

        private void CacheAllTabs()
        {
            var tabSettings = _settings.LoadSetting<TabSettings>();
            //update tab cache
            if (tabSettings.CacheMenuItems)
            {
                var tabs = _tabSvc.GetAll().ToList<Tab>();
                _cacheMgr.Set("TabManager.CacheMenuItems", tabs, 30);
            }
            tabSettings = null;

        }

        private List<Tab> GetAllTabs()
        {
            var tabSettings = _settings.LoadSetting<TabSettings>();

            if (tabSettings.CacheMenuItems)
            {
                var tabs = _cacheMgr.Get<List<Tab>>("TabManager.CacheMenuItems");
                if (tabs != null && tabs.Count > 0)
                {
                    tabSettings = null;
                    return tabs;
                }
            }

            tabSettings = null;

            return (from tab in _tabSvc.GetAll()
                    orderby tab.TabOrder
                    select tab).ToList();
        }
        #endregion
    }
}
